home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / encode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-08  |  7.0 KB  |  268 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: encode.c,v 5.5 1993/05/08 20:25:33 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.5 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: encode.c,v $
  17.  * Revision 5.5  1993/05/08  20:25:33  syd
  18.  * Add sleepmsg to control transient message delays
  19.  * From: Syd
  20.  *
  21.  * Revision 5.4  1993/04/12  01:26:06  syd
  22.  * According to the SVID (version 3) the function crypt is
  23.  *
  24.  *     char *     crypt( const char *, const char * )
  25.  *
  26.  * However, it is declared as
  27.  *
  28.  *     unsigned char crypt();
  29.  *
  30.  * on line 179 of src/encode.c.  The "unsigned" keyword causes the compile
  31.  * to fail on SVID3 compliant systems.  Upon inspection, it appeared that
  32.  * the declaration was not even required if CRYPT was not defined, so
  33.  * changed it to be conditionally compiled.
  34.  * From: Larry Philps <larryp@sco.COM>
  35.  *
  36.  * Revision 5.3  1993/02/03  17:12:53  syd
  37.  * move more declarations to defs.h, including sleep
  38.  * From: Syd
  39.  *
  40.  * Revision 5.2  1992/12/07  02:34:56  syd
  41.  * Traditional C used 'unsigned preserving' rules when an integral data
  42.  * value is widened to integer and ANSI C changed the rules to 'value
  43.  * preserving'. This is one of the few things that the ANSI X3J11 comitte
  44.  * did that might break existing programs.  Casting to (int)
  45.  * From: Bo.Asbjorn.Muldbak <bam@jutland.ColumbiaSC.NCR.COM>
  46.  *
  47.  * Revision 5.1  1992/10/03  22:58:40  syd
  48.  * Initial checkin as of 2.4 Release at PL0
  49.  *
  50.  *
  51.  ******************************************************************************/
  52.  
  53. /** This is a heavily mangled version of the 'cypher' program written by
  54.     person or persons unknown.  
  55.  
  56. **/
  57.  
  58. #include "headers.h"
  59. #include "s_elm.h"
  60.  
  61. #define RTRSZ    94
  62. #define RN    4
  63. #define RMASK    0x7fff    /* use only 15 bits */
  64.  
  65. /*
  66.  *  NOTICE: Some systems take a char as a signed value,
  67.  *        a byte wide int. For encryption to work you
  68.  *        absolutely need an unsigned char !!
  69.  *        According to K&R2 and ANSI it is always
  70.  *        permissible to specify unsigned with char.
  71.  *        (ukkonen@csc.fi)
  72.  */
  73.  
  74. static unsigned char    r[RTRSZ][RN];    /* rotors */
  75. static unsigned char    ir[RTRSZ][RN];    /* inverse rotors */
  76. static unsigned char    h[RTRSZ];        /* half rotor */
  77. static unsigned char    s[RTRSZ];        /* shuffle vector */
  78. static int        p[RN];        /* rotor indices */
  79.  
  80. static unsigned char the_key[SLEN];    /* unencrypted key */
  81. static unsigned char *encrypted_key;    /* encrypted key   */
  82.  
  83. static char *decrypt_prompt = NULL;
  84. static char *first_enc_prompt = NULL;
  85. static char *second_enc_prompt = NULL;
  86. #define PROMPT_LINE        LINES-1
  87.  
  88. getkey(send)
  89. int send;
  90. {
  91.     /** this routine prompts for and returns an encode/decode
  92.         key for use in the rest of the program. **/
  93.  
  94.     char buffer[2][NLEN];
  95.  
  96.     if (decrypt_prompt == NULL) {
  97.         decrypt_prompt = catgets(elm_msg_cat, ElmSet, ElmDecryptPrompt,
  98.             "Enter decryption key: ");
  99.         first_enc_prompt = catgets(elm_msg_cat, ElmSet, ElmFirstEncryptPrompt,
  100.             "Enter encryption key: ");
  101.         second_enc_prompt = catgets(elm_msg_cat, ElmSet, ElmSecondEncryptPrompt,
  102.             "Please enter it again: ");
  103.     }
  104.  
  105.     while (1) {
  106.       PutLine0(PROMPT_LINE, 0, (send ? first_enc_prompt : decrypt_prompt));
  107.       CleartoEOLN();
  108.       optionally_enter(buffer[0], PROMPT_LINE,
  109.         strlen(send ? first_enc_prompt : decrypt_prompt), FALSE, TRUE);
  110.       if (send) {
  111.         PutLine0(PROMPT_LINE, 0, second_enc_prompt);
  112.         CleartoEOLN();
  113.         optionally_enter(buffer[1], PROMPT_LINE, strlen(second_enc_prompt),
  114.           FALSE, TRUE);
  115.         if(strcmp(buffer[0], buffer[1]) != 0) {
  116.           error(catgets(elm_msg_cat, ElmSet, ElmKeysNotSame,
  117.         "Your keys were not the same!"));
  118.           if (sleepmsg > 0)
  119.             sleep(sleepmsg);
  120.           clear_error();
  121.           continue;
  122.         }
  123.       }
  124.       break;
  125.     }
  126.         strcpy((char *) the_key, buffer[0]);    /* save unencrypted key */
  127.     makekey(buffer[0]);
  128.  
  129.     setup();        /** initialize the rotors etc. **/
  130.  
  131.     ClearLine(PROMPT_LINE);        
  132.     clear_error();
  133. }
  134.  
  135. get_key_no_prompt()
  136. {
  137.     /** This performs the same action as get_key, but assumes that
  138.         the current value of 'the_key' is acceptable.  This is used
  139.         when a message is encrypted twice... **/
  140.  
  141.     char buffer[SLEN];
  142.  
  143.     strcpy(buffer, (char *) the_key);
  144.  
  145.     makekey( buffer );
  146.  
  147.     setup();
  148. }
  149.  
  150. encode(line)
  151. char *line;
  152. {
  153.     /** encrypt or decrypt the specified line.  Uses the previously
  154.         entered key... **/
  155.  
  156.     register int i, j, ph = 0;
  157.  
  158.     for (; *line; line++) {
  159.       i = (int) *line;
  160.  
  161.       if ( (i >= ' ') && (i < '~') ) {
  162.         i -= ' ';
  163.  
  164.         for ( j = 0; j < RN; j++ )        /* rotor forwards */
  165.           i = r[(i+p[j])%RTRSZ][j];
  166.  
  167.         i = (((int)h[(i+ph)%RTRSZ])-ph+RTRSZ)%RTRSZ;    /* half rotor */
  168.  
  169.         for ( j--  ; j >= 0; j-- )        /* rotor backwards */
  170.           i = ((int)ir[i][j]+RTRSZ-p[j])%RTRSZ;
  171.  
  172.         j = 0;                /* rotate rotors */
  173.         p[0]++;
  174.         while ( p[j] == RTRSZ ) {
  175.           p[j] = 0;
  176.           j++;
  177.           if ( j == RN ) break;
  178.           p[j]++;
  179.             }
  180.   
  181.         if ( ++ph == RTRSZ )
  182.           ph = 0;
  183.  
  184.         i += ' ';
  185.       }
  186.       
  187.       *line = (char) i;    /* replace with altered one */
  188.     }
  189. }
  190.  
  191.  
  192. makekey( rkey)
  193. char *rkey;
  194. {
  195.     /** encrypt the key using the system routine 'crypt' **/
  196.  
  197.     static char key[9];
  198.     char salt[2];
  199. #ifdef CRYPT
  200.     char *crypt();
  201. #endif /* CRYPT */
  202.  
  203.     strncpy( key, rkey, 8);
  204.     key[8] = '\0';
  205.     salt[0] = key[0];
  206.     salt[1] = key[1];
  207. #ifdef CRYPT
  208.     encrypted_key = (unsigned char *) crypt( key, salt);
  209. #else
  210.     encrypted_key = (unsigned char *) key;
  211. #endif
  212. }
  213.  
  214. /*
  215.  * shuffle rotors.
  216.  * shuffle each of the rotors indiscriminately.  shuffle the half-rotor
  217.  * using a special obvious and not very tricky algorithm which is not as
  218.  * sophisticated as the one in crypt(1) and Oh God, I'm so depressed.
  219.  * After all this is done build the inverses of the rotors.
  220.  */
  221.  
  222. setup()
  223. {
  224.     register long i, j, k, temp;
  225.     long seed;
  226.  
  227.     for ( j = 0; j < RN; j++ ) {
  228.         p[j] = 0;
  229.         for ( i = 0; i < RTRSZ; i++ )
  230.             r[i][j] = i;
  231.     }
  232.  
  233.     seed = 123;
  234.     for ( i = 0; i < 13; i++)        /* now personalize the seed */
  235.       seed = (seed*encrypted_key[i] + i) & RMASK;
  236.  
  237.     for ( i = 0; i < RTRSZ; i++ )        /* initialize shuffle vector */
  238.       h[i] = s[i] = i;
  239.  
  240.     for ( i = 0; i < RTRSZ; i++) {        /* shuffle the vector */
  241.       seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
  242.       k = ((seed % 65521) & RMASK) % RTRSZ;
  243.       temp = s[k];
  244.       s[k] = s[i];
  245.       s[i] = temp;
  246.     }
  247.  
  248.     for ( i = 0; i < RTRSZ; i += 2 ) {    /* scramble the half-rotor */
  249.       temp = h[s[i]];            /* swap rotor elements ONCE */
  250.       h[s[i]] = h[s[i+1]];
  251.       h[s[i+1]] = temp;
  252.     }
  253.  
  254.     for ( j = 0; j < RN; j++) {            /* select a rotor */
  255.  
  256.       for ( i = 0; i < RTRSZ; i++) {        /* shuffle the vector */
  257.         seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
  258.         k = ((seed % 65521) & RMASK) % RTRSZ;
  259.         temp = r[i][j];
  260.         r[i][j] = r[k][j];
  261.         r[k][j] = temp;
  262.       }
  263.  
  264.       for ( i = 0; i < RTRSZ; i++)         /* create inverse rotors */
  265.         ir[r[i][j]][j] = i;
  266.        }
  267. }
  268.